package com.asm.protocol;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.TooLongFrameException;

/**
 * 协议包结构体
 */
public class ProcotolFrameDecoder extends LengthFieldBasedFrameDecoder {

    public ProcotolFrameDecoder() {
        this(
            1024, // 最大包长度
            12, // 协议包中length字段前面有多少个字节
            4, // length字段占几个字节
            0, // 当length表示整包长度时，该参数为一个负数，该参数与length相加表示报文体长度，我们规定的length就是指报文体长度，因此该字段设为0
            0); // 当前handler向后传递字节序时，忽略整体报文的前多少个字节，只返回剩余字节
    }

    public ProcotolFrameDecoder(
             int maxFrameLength,
             int lengthFieldOffset,
             int lengthFieldLength,
             int lengthAdjustment,
             int initialBytesToStrip) {
        super(maxFrameLength, lengthFieldOffset, lengthFieldLength,lengthAdjustment, initialBytesToStrip);
    }

    /**
     * 重写decode方法，对于超长frame，decode方法默认处理策略是忽略，此处修改默认策略，发现超长frame则关闭socket
     * @param ctx
     * @param in
     * @return
     * @throws Exception
     */
    @Override
    protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        try {
            return super.decode(ctx, in);
        } catch (TooLongFrameException e) {
            // log.error("frame too long", e);
            ctx.channel().close(); // 包超长则直接关闭channel，从tail开始向前依次回调close，最终回调head.close
            // ctx.close(); // 从当前handler开始，向前依次回调close，最终回调head.close
            throw  e;
        }
    }


}
